/*==========================================================================*\
 |  $Id: PrintExpression.java 9 2009-11-06 02:47:13Z VTWoods $
 |*-------------------------------------------------------------------------*|
 |  Copyright (C) 2009 Virginia Tech
 |
 |  This file is part of CloudSpace.
 |
 |  CloudSpace is free software; you can redistribute it and/or modify
 |  it under the terms of the GNU General Public License as published
 |  by the Free Software Foundation; either version 3 of the License, or
 |  (at your option) any later version.
 |
 |  CloudSpace is distributed in the hope that it will be useful,
 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 |  GNU General Public License for more details.
 |
 |  You should have received a copy of the GNU General Public License
 |  along with CloudSpace; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/

package student.web;

import org.zkoss.zk.scripting.util.GenericInterpreter;

//-------------------------------------------------------------------------
/**
 * Evaluate and echo the contents of a Java expression, such as an
 * arbitrary method call.
 * <p>A &lt;print-expression&gt; tag has one required property and two
 * optional properties:
 * </p>
 * <dl>
 * <dt><b>Parameters</b></dt>
 * <dd><code>type</code> - The (optional) Java type of the expression--this
 *   should be a legal Java class name that is in scope (see
 *   {@link Import}) (<b>must</b> come before the value!).</dd>
 * <dd><code>isHtml</code> - A boolean that indicates whether the expression
 * should be treated as a string of HTML text, or whether any special HTML
 * entities in the value should be escaped so they show up correctly in
 * web browsers.  (<b>Must</b> come before the value!)</dd>
 * <dd><code>value</code> - The expression to print.  It can be any Java
 *   expression, or any EL expression (i.e., ${...}), but may not be a
 *   bound data value (no @{...}).</dd>
 * </dl>
 * <p>Examples:</p>
 * <pre>
 * &lt;print-expression value="myString.substring(pos, subLen)"/&gt;
 *
 * &lt;!-- With an included type --&gt;
 * &lt;print-expression type="URL" value="myWebBot.getPageURL()"/&gt;
 *
 * &lt;!-- If you use quotes, they must be HTML-escaped --&gt;
 * &lt;print-expression
 *   value="&amp;quot;string &amp;quot; + &amp;quot;concatenation&amp;quot;"/&gt;
 *
 * &lt;!-- A longer version, so you don't have to escape the quotes. --&gt;
 * &lt;print-expression&gt;
 *   &lt;attribute name="value"&gt;
 *     "Name: " + person.getLastName() + ", " + person.getFirstName()
 *   &lt;/attribute&gt;
 * &lt;/variable&gt;
 * </pre>
 *
 * @author Stephen Edwards
 * @author Last changed by $Author: VTWoods $
 * @version $Revision: 9 $, $Date: 2009-11-06 02:47:13 +0000 (Fri, 06 Nov 2009) $
 */
public class PrintExpression
    extends org.zkoss.zhtml.Text
{
    //~ Constructor ...........................................................

    // ----------------------------------------------------------
    /**
     * Creates a new PrintExpression component.
     */
    public PrintExpression()
    {
        super();
    }


    //~ Public methods ........................................................

    // ----------------------------------------------------------
    /**
     * Accessor for the "type" property, which may be null if no type
     * has been specified.
     * @return The expressions's type (a Java {@link Class} name)
     */
    public String getType()
    {
        return type;
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "type" property, which is optional.  Note that the
     * expression type, if used, must be set before the value (which means the
     * type attribute must appear to the left of the value attribute in your
     * ZHTML code).
     * @param newType The type (class) to use for the variable.  The class
     * name specified must either be fully qualified, or must have been
     * imported (see {@link Import}).
     */
    public void setType(String newType)
    {
        type = newType;
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "value" property, which provides the variable's initial
     * value.  It must come after the name and (optional) type.
     * @param value The value to use for the variable.  It must
     * be an object of the appropriate type.
     */
    public void setValue(Object value)
    {
        String result = "null";
        if (value != null)
        {
            try
            {
                result = value.toString();
            }
            catch(Exception e)
            {
                student.web.internal.Exceptions.addSimpleExceptionGrid(
                    getParent(), e, "In &lt;print-expression&gt; tag, "
                    + "calling toString() on specified value");
            }
            if (!isHtml)
            {
                result = student.web.internal.Exceptions.escapeHtml(result);
            }
        }
        super.setValue(result);
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "value" property, which provides the variable's initial
     * value.  It must come after the name and (optional) type.
     * @param value A string that will be interpreted as a Java expression
     * of the appropriate type to produce the desired variable value.
     */
    public void setValue(String value)
    {
        GenericInterpreter interpreter = (GenericInterpreter)getPage()
            .getInterpreter( getPage().getZScriptLanguage() );
        if (value != null)
        {
            try
            {
                interpreter.interpret(
                        (type == null ? "" : (type + " "))
                        + TEMP_VAR + " = " + value + ";",
                        getNamespace() );
                Object val =
                    interpreter.getVariable( getNamespace(), TEMP_VAR );
                interpreter.unsetVariable( getNamespace(), TEMP_VAR );
                setValue(val);
            }
            catch(Exception e)
            {
                student.web.internal.Exceptions.addSimpleExceptionGrid(
                    getParent(), e, "In &lt;print-expression&gt; tag for "
                    + "value \"" + value + "\"");
            }
        }
    }


    // ----------------------------------------------------------
    /**
     * Accessor for the "isHtml" property.  Indicates whether or not
     * the expression should be treated as formatted HTML text, or as
     * plain text.
     * @return true if the expression is interpreted as already HTML-encoded
     */
    public boolean getIsHtml()
    {
        return isHtml;
    }


    // ----------------------------------------------------------
    /**
     * Mutator for the "isHtml" property, which is optional.  If used, it
     * must be set before the value (which means the isHtml attribute must
     * appear to the left of the value attribute in your ZHTML code).
     * @param value True if this expression should be treated as HTML, or
     * false if it should be treated as non-HTML (meaning any HTML entities
     * should be properly escaped before the value is printed).
     */
    public void setIsHtml(boolean value)
    {
        isHtml = value;
    }


    //~ Instance/static variables .............................................

    private boolean isHtml;
    private String  type;
    final static private String TEMP_VAR = "__PrintExpressionTemp";
}
